home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / Sherlock 2.0 / Sherlock_DevLib / sl_macro.c < prev    next >
Text File  |  1996-04-06  |  14KB  |  754 lines

  1. /*
  2.     Sherlock run-time macros.
  3.  
  4.     source:  sl_macro.c
  5.     started: November 4, 1993.
  6.     version:
  7.         April 5, 1996.
  8.             Changed computation of time in sl_ret.
  9.         February 5, 1996.
  10.             Added support for Symantec C.
  11.         November 15,1995
  12.             Added sl_unwatch.
  13.         January 7, 1994
  14. */
  15.  
  16. #include <LIBlib.h>
  17.  
  18. #include <sl.h>
  19. #include <sl2.h>
  20.  
  21. #include <LIBenv.h>
  22. #include <LIBmem.h>
  23.  
  24. #include <string.h>
  25. #include <stdlib.h>
  26.  
  27. /*
  28.     All Sherlock macros will produce output if PRINT_EVERYTHING is #defined.
  29.     This logic was installed to test code generation in CC2.
  30. */
  31. #if 0 && defined(applec)
  32.     #define PRINT_EVERYTHING
  33. #endif
  34.  
  35. /*
  36.     Global variable set by sl_ret.
  37. */
  38. long sl_theTicks;
  39. sl_wnode * sl_wlist = NULL;
  40. long sl_min_margin = 0;
  41. long sl_margin_start = 0;
  42. bool sl_time_flag = TRUE;        /* TRUE: report time in exit macros. */
  43. unsigned long sl_count = 0;        /* The time returned by the interrupt timer. */
  44.  
  45. /*
  46.     Function prototypes of routines local to this file.
  47. */
  48. static void sl_name_net    (char *s);
  49. static int    sl_ret        (char *s);
  50. static int    sl_visit    (sl_node *np, int stat_flag, int entry_flag, char *s);
  51.  
  52. /*
  53.     Declare variables local to this file.
  54. */
  55. static long    sl_net;        /* time Count .        */
  56.  
  57. /*
  58.     Do not change the values of the following abbreviations.
  59. */
  60. #define STAT_FLAG        1
  61. #define NO_STAT_FLAG    0
  62. #define ENTRY_FLAG        1
  63. #define NO_ENTRY_FLAG    0
  64.  
  65. /*
  66.     Return a pointer to the statistics node for s.
  67. */
  68. sl_node *
  69. sl_find_name(char *s)
  70. {
  71.     return sl_find(NULL, s);
  72. }
  73.  
  74. /*
  75.     Output name and ticks.
  76. */
  77. static void
  78. sl_name_net(char *s)
  79. {
  80.     epads(s, sl_nodots ? 20 : 0);
  81.  
  82.     if (sl_time_flag) {
  83.         es(" (");
  84.         epadmsec(sl_net, sl_nodots ? 3 : 0);
  85.         es(" msec.) ");
  86.     }
  87.     else {
  88.         es(": ");
  89.     }
  90. }
  91.  
  92. /*
  93.     Begin and end a section of overhead that does not contribute to statistics.
  94. */
  95. void
  96. sl_ovb(void)
  97. {
  98.     register sl_snode * sp;
  99.  
  100.     if (sl_stack == NULL) {
  101.         sl_abort(SL_ABORT_OVB);
  102.     }
  103.     if (sl_level-1 >= 0 && sl_level-1 < SL_MAX_STACK) {
  104.         sp = &sl_stack [sl_level-1];
  105.         if (sp -> overstart == 0) {
  106.             sp -> overstart = sl_ticks();
  107.         }
  108.     }
  109. }
  110.  
  111. void
  112. sl_ovx(void)
  113. {
  114.  
  115.     register sl_snode *    sp;
  116.     long                the_overhead;
  117.  
  118.     if (sl_stack == NULL) {
  119.         sl_abort(SL_ABORT_OVX);
  120.     }
  121.     if (sl_level-1 >= 0 && sl_level-1 < SL_MAX_STACK) {
  122.         sp = &sl_stack [sl_level-1];
  123.         if (sp -> overstart != 0) {
  124.             the_overhead = sl_ticks() - sp -> overstart;
  125.             if (the_overhead < 0) {
  126.                 the_overhead = 0;
  127.             }
  128.             sp -> overhead += the_overhead;
  129.             sp -> overstart = 0;
  130.         }
  131.     }
  132. }
  133.  
  134. /*
  135.     TRACEPX macro.
  136. */
  137. int
  138. sl_pxtrace(char *s)
  139. {
  140.     if (sl_ret(s)) {
  141.         sl_dots(sl_level);
  142.         sl_name_net(s);
  143.         return TRUE;
  144.     }
  145.     else {
  146.         return FALSE;
  147.     }
  148. }
  149.  
  150. /*
  151.     Check for proper stack alignment using the entry name s.
  152.     Return TRUE if tracing is enabled.
  153. */
  154.  
  155. static bool watch_flag = FALSE;
  156.  
  157. static int
  158. sl_ret(char *s)
  159. {
  160.     register sl_snode * sp;
  161.     register sl_node * np;
  162.     register sl_node * np2;
  163.     register long raw_time = 0;
  164.     
  165.     long time = 0;
  166.     char * s2 = s;
  167.  
  168.     if (sl_troff || sl_stack == NULL) {
  169.         return FALSE;
  170.     }
  171.  
  172. #if 0 // defined(THINK_C) // Doesn't work on PowerPc
  173.     /* Set the minimum stack pointer. */
  174.     {
  175.         long margin = env_stackMargin();
  176.         if (sl_min_margin > margin) {
  177.             sl_min_margin = margin;
  178.         }
  179.     }
  180. #endif
  181.  
  182.     /* Check the watch list. */
  183.     if (sl_wlist) {
  184.         sl_watchall();
  185.     }
  186.  
  187.     /*
  188.         Go to the previous level.
  189.     */
  190.     if (sl_level <= 0) {
  191.         es("Sherlock underflow at "); es(s);
  192.         es("\nCheck for missing or misnamed exit macros.");
  193.         enl();
  194.         sl_dumpstk();
  195.         sl_exit();
  196.     }
  197.     else {
  198.         sl_level--;
  199.     }
  200.  
  201.     sp = &sl_stack [sl_level];
  202.     np = sp -> node;
  203.  
  204.     if (*s == '!' || *s == '-') {
  205.         s2 = s+1;
  206.     }
  207.     if (strcmp(np -> name, s2) != 0) {
  208.  
  209.         ecnl();
  210.         es("sl_ret: Entry/Exit mismatch at exit point "); es(s); enl();
  211.         es("Expecting "); es(np -> name);
  212.         es(" got "); es(s2); enl();
  213.         es("Check for missing or misnamed exit macros.");
  214.         enl();
  215.         sl_dumpstk();
  216.         sl_exit();
  217.     }
  218.  
  219.     if (sp -> overstart != 0) {
  220.         ecnl(); es("sl_ret: unterminated SL_OVB at exit point "); es(s); enl();
  221.         es("Check for missing SL_OVX macros.");
  222.         enl();
  223.         sl_dumpstk();
  224.         sl_exit();
  225.     }
  226.  
  227.     /*
  228.         Update the regular statistics for the node at this level.
  229.  
  230.         Set sl_net for sl_name_net.
  231.     */
  232.     
  233.     #ifdef SL_USE_MICROSECONDS
  234.     {
  235.         /*
  236.             Compute time = wide_stop_time - sp -> wide_start.
  237.             
  238.             We assume that the interval between the start time and stop time
  239.             is be less than 2**32 microseconds, about 1 hour.
  240.         */
  241.         UnsignedWide wide_stop_time;
  242.         Microseconds(&wide_stop_time);
  243.         time = wide_stop_time.lo - sp -> wide_start.lo;
  244.     }
  245.         
  246.     #else
  247.     
  248.         raw_time = sl_ticks();
  249.         time = raw_time - sp -> start;
  250.     
  251.     #endif
  252.  
  253.     if (time < 0) {
  254.         if (sl_warning) {
  255.             ecnl(); es("Negative time: "); es(sp -> node -> name);
  256.             es(" sl_level: "); eint(sl_level);
  257.             es(" raw time: "); ehex(raw_time);
  258.             es(" start: "); ehex(sp -> start); enl();
  259.         }
  260.         sl_neg_count++;
  261.         time = 0;
  262.     }
  263.     sl_theTicks = sl_net = time;
  264.  
  265.     np -> time += (time - sp -> overhead);
  266.     sp -> overhead = 0L;
  267.  
  268.     /*
  269.         Update the cumulative statistics for the previous node, if any.
  270.  
  271.         Add the total time at this level to the *overhead* at the
  272.         previous level so only the time spent at that level is counted.
  273.     */
  274.     if (sl_level > 0) {
  275.         sp = &sl_stack [sl_level-1];
  276.         sp -> overhead    += time;
  277.  
  278.         np2 = sp -> node;
  279.         np2 -> time2 += time;
  280.     }
  281.  
  282.     /* Return TRUE if we should enable the macro. */
  283.     #ifdef PRINT_EVERYTHING
  284.         if (*s != '-') {
  285.             return TRUE;
  286.         }
  287.     #endif
  288.  
  289.     if (s[0] == '!') {
  290.         return !((np -> trace) & SL_TRACE_BIT);
  291.     }
  292.     else if (s[0] == '-') {
  293.         return ((np -> trace) & SL_TRACE_BIT) && !((np -> trace) & SL_WILD_BIT);
  294.     }
  295.     else {
  296.         return (np -> trace) & SL_TRACE_BIT;
  297.     }
  298. }
  299.  
  300. void
  301. sl_unwatch(char * p, long length)
  302. {
  303.     sl_wnode * p2 = NULL;
  304.     sl_wnode * p3 = NULL;
  305.         
  306.     if (p == NULL || sl_wlist == NULL)
  307.     {
  308.         ecnl(); es("sl_unwatch: NULL p or sl_wlist!\n");
  309.         return;
  310.     }
  311.     
  312.     if (p == sl_wlist -> wp)
  313.     {
  314.         p3 = sl_wlist;
  315.         sl_wlist = sl_wlist -> wnext;
  316.     }
  317.     else
  318.     {
  319.         p2 = sl_wlist;
  320.         p3 = sl_wlist -> wnext;
  321.         while (p3)
  322.         {
  323.             if (p == p3 -> wp)
  324.             {
  325.                 p2 -> wnext = p3 -> wnext;
  326.                 break;
  327.             }
  328.             p2 = p3;
  329.             p3 = p3 -> wnext;
  330.         }
  331.     }
  332.     
  333.     if (p3)
  334.     {
  335.         if (length != p3 -> wlength)
  336.         {
  337.             ecnl(); es("sl_unmatch: mismatched lengths!\n");
  338.             abort();
  339.         }
  340.         es("Unwatching block: "); es(p3 -> wtag);
  341.         es(" at "); eptr(p3 -> wp);
  342.         es(" length: "); elong(p3 -> wlength); enl();
  343.         
  344.         lib_free(p3 -> wsavep);
  345.         lib_free(p3);
  346.     }
  347. }
  348.  
  349. /*
  350.     Visit node p.
  351.     Update tick statistics if stat_flag is TRUE.
  352.     Enter a section of timing code if entry_flag is TRUE.
  353.     Return TRUE if the node is currently enabled.
  354. */
  355. static int
  356. sl_visit(register sl_node *np, int stat_flag, int entry_flag, char * s)
  357. {
  358.     register sl_snode * sp;
  359.  
  360.     if (np == NULL || sl_stack == NULL) {
  361.         return FALSE;
  362.     }
  363.  
  364. #if 0 // defined(THINK_C) // Doesn't work on PowerPc
  365.     /* Set the minimum stack pointer. */
  366.     {
  367.         long margin = env_stackMargin();
  368.         if (sl_min_margin > margin) {
  369.             sl_min_margin = margin;
  370.         }
  371.     }
  372. #endif
  373.  
  374.     /* Check the watch list. */
  375.     if (sl_wlist) {
  376.         sl_watchall();
  377.     }
  378.  
  379.     /* Update statistics if requested. */
  380.     if (stat_flag) {
  381.         np -> calls++;
  382.     }
  383.  
  384.     /* Make an entry in the call stack for entry macros. */
  385.     if (entry_flag && sl_level < SL_MAX_STACK) {
  386.  
  387.         /* Initialize the statistics. */
  388.         sp = &sl_stack[sl_level++];
  389.         sp -> node        = np;
  390.         sp -> start        = sl_ticks();
  391.         #ifdef SL_USE_MICROSECONDS
  392.             Microseconds(&sp -> wide_start);
  393.         #endif
  394.         sp -> overhead    = 0L;
  395.         sp -> overstart = 0L;
  396.  
  397.         sl_lmax = sl_level;
  398.     }
  399.  
  400.     /* Return TRUE if macro should be enabled. */
  401.     #ifdef PRINT_EVERYTHING
  402.         if (s[0] != '-') {
  403.             return TRUE;
  404.         }
  405.     #endif
  406.  
  407.     if (s[0] == '!') {
  408.         return !((np -> trace) & SL_TRACE_BIT);
  409.     }
  410.     else if (s[0] == '-') {
  411.         return ((np -> trace) & SL_TRACE_BIT) && !((np -> trace) & SL_WILD_BIT);
  412.     }
  413.     else {
  414.         return (np -> trace) & SL_TRACE_BIT;
  415.     }
  416. }
  417.  
  418. /*
  419.     Add an item to the watch list.
  420. */
  421. void
  422. sl_watch(void * block_p, long block_length, char * tag)
  423. {
  424.     /* Major bug! fixed 6/15/93: allocate sizeof(sl_wnode) bytes, not sl_node bytes! */
  425.     register sl_wnode * p = lib_calloc( (size_t) 1, sizeof(sl_wnode));
  426.     register long c;
  427.  
  428.     p -> wnext = sl_wlist;
  429.     sl_wlist = p;
  430.     p -> wp = block_p;
  431.     p -> wlength = block_length;
  432.     p -> wsavep = lib_calloc( (size_t) 1, block_length);
  433.     p -> wtag = tag;
  434.     memmove(p -> wsavep, block_p, block_length);
  435.     ecnl();
  436.     es("Watching block: "); es(p -> wtag); es(" at "); eptr(p -> wp); es("... ");
  437.     if (p -> wlength > 10) {
  438.         enl();
  439.     }
  440.     if (p -> wlength < 20) {
  441.         for (c = 0; c < p -> wlength; c++) {
  442.             if ((c % 10) == 9) enl();
  443.             eblank(); epadhex(((p -> wsavep)[c]) & 0xff, 2); eblank();
  444.         }
  445.     }
  446.     ecnl();
  447. }
  448.  
  449. /*
  450.     Watch all items on the watch list.
  451. */
  452. void
  453. sl_watchall(void)
  454. {
  455.     register sl_wnode * p;
  456.     register long i;
  457.  
  458.     for (p = sl_wlist; p; p = p -> wnext) {
  459.         if (memcmp(p -> wp, p -> wsavep, p -> wlength) != 0) {
  460.             ecnl();
  461.             es("Watch block: "); es(p -> wtag);
  462.             es(" changed.  Base: "); eptr(p -> wp); enl();
  463.             if (p -> wlength < 20) {
  464.                 es("Before..."); enl();
  465.                 for (i = 0; i < p -> wlength; i++) {
  466.                     if ((i % 10) == 9) enl();
  467.                     eblank(); epadhex(((p -> wsavep)[i]) & 0xff, 2); eblank();
  468.                 }
  469.                 es("\nAfter..."); enl();
  470.                 for (i = 0; i < p -> wlength; i++) {
  471.                     if ((i % 10) == 9) enl();
  472.                     eblank(); epadhex(((p -> wp)[i]) & 0xff, 2);
  473.                     es((p -> wp[i] == p -> wsavep[i]) ? " " : "*");
  474.                 }
  475.             }
  476.             else {
  477.                 int linecount = 0;
  478.                 long start, finish;
  479.                 for(i = 0; p -> wp[i] == p -> wsavep[i]; i++) {
  480.                     ;
  481.                 }
  482.                 start = i;
  483.                 for(i = start; i < p -> wlength; i++) {
  484.                     if (p -> wp[i] != p -> wsavep[i]) {
  485.                         finish = i;
  486.                     }
  487.                 }
  488.                 finish++;
  489.                 epads("offset:", 7); epads("before", 7); epads("after", 7); enl();
  490.                 for (i = start; i < finish; i++) {
  491.                     epadlong(i, 5); es(":");
  492.                     eblank(); epadhex(((p -> wsavep)[i]) & 0xff, 2);
  493.                     eblank(); epadhex(((p -> wp)[i])     & 0xff, 2);
  494.                     es((p -> wp[i] == p -> wsavep[i]) ? " " : "*");
  495.                     if ((++linecount % 4) == 3) {
  496.                         enl();
  497.                     }
  498.                 }
  499.             }
  500.             ecnl();
  501.             memmove(p -> wsavep, p -> wp, p -> wlength);
  502.             sl_dumpstk(); ecnl();
  503.             abort();
  504.         }
  505.     }
  506. }
  507.  
  508. /*
  509.     TICKX macro--Exit a nesting level and print s.
  510. */
  511. void
  512. sl_x(char *s)
  513. {
  514.     if (sl_ret(s)) {
  515.         sl_dots(sl_level);
  516.         sl_name_net(s);
  517.         es("exits");
  518.         enl();
  519.     }
  520. }
  521.  
  522. /*
  523.     STATX and TRACEX macros.
  524. */
  525. int
  526. sl_xtrace(char *s)
  527. {
  528.     /* 4/9/93: Trace as with TICKB if sl_full_trace flag is on. */
  529.     if (sl_ret(s)) {
  530.  
  531.         #ifdef PRINT_EVERYTHING
  532.             sl_dots(sl_level);
  533.             sl_name_net(s);
  534.             ecnl();
  535.         #else
  536.             if (sl_full_trace) {
  537.                 sl_dots(sl_level);
  538.                 sl_name_net(s);
  539.                 ecnl();
  540.             }
  541.         #endif
  542.  
  543.         return TRUE;
  544.     }
  545.     else {
  546.         return FALSE;
  547.     }
  548. }
  549.  
  550. /*
  551.     STATB macro--Enter a new nesting level.
  552.     (Mark II Version).
  553. */
  554. void
  555. sl2bstat(sl_node **pp, char *s)
  556. {
  557.     if (*pp == NULL) {
  558.         *pp = sl_find("STATB", s);
  559.     }
  560.  
  561.     /* 4/9/93: Trace as with TICKB if sl_full_trace flag is on. */
  562.     if (sl_visit(*pp, STAT_FLAG, ENTRY_FLAG, s)) {
  563.  
  564.         #ifdef PRINT_EVERYTHING
  565.             sl_dots(sl_level-1);
  566.             es(s); es(":"); enl();
  567.         #else
  568.             if (sl_full_trace) {
  569.                 sl_dots(sl_level-1);
  570.                 es(s); es(":"); enl();
  571.             }
  572.         #endif
  573.     }
  574. }
  575.  
  576. /*
  577.     TICKB or ENTER macros--Enter a new nesting level.
  578.     (Mark II Version).
  579. */
  580. void
  581. sl2btick(sl_node **pp, char *s)
  582. {
  583.     if (*pp == NULL) {
  584.         *pp = sl_find("TICKB", s);
  585.     }
  586.  
  587.     if (sl_visit(*pp, STAT_FLAG, ENTRY_FLAG, s)) {
  588.         sl_dots(sl_level-1);
  589.         es(s); es(":"); enl();
  590.     }
  591. }
  592.  
  593. /*
  594.     TRACEB macro--Enter a new nesting level.
  595.     (Mark II Version).
  596. */
  597. int
  598. sl2btrace(sl_node **pp, char *s)
  599. {
  600.     if (*pp == NULL) {
  601.         *pp = sl_find("TRACEB", s);
  602.     }
  603.     /* 4/9/93: Trace as with TICKB if sl_full_trace flag is on. */
  604.     if (sl_visit(*pp, STAT_FLAG, ENTRY_FLAG, s)) {
  605.  
  606.         #ifdef PRINT_EVERYTHING
  607.             sl_dots(sl_level-1);
  608.             es(s); es(":"); enl();
  609.         #else
  610.             if (sl_full_trace) {
  611.                 sl_dots(sl_level-1);
  612.                 es(s); es(":"); enl();
  613.             }
  614.         #endif
  615.  
  616.         return TRUE;
  617.     }
  618.     else {
  619.         return FALSE;
  620.     }
  621. }
  622.  
  623. /*
  624.     TICKN macro.
  625.     (Mark II Version.)
  626. */
  627. void
  628. sl2ntick(sl_node **pp, char * s)
  629. {
  630.     if (*pp == NULL) {
  631.         *pp = sl_find("TICKN", s);
  632.     }
  633.  
  634.     if (sl_visit(*pp, NO_STAT_FLAG, NO_ENTRY_FLAG, s)) {
  635.         sl_dots(sl_level-1);
  636.         es(s); es(":"); enl();
  637.     }
  638. }
  639.  
  640. /*
  641.     TRACEN macro.
  642.     (Mark II Version.)
  643. */
  644. int
  645. sl2ntrace(sl_node **pp, char *s)
  646. {
  647.     if (*pp == NULL) {
  648.         *pp = sl_find("TRACEN", s);
  649.     }
  650.     return sl_visit(*pp, NO_STAT_FLAG, NO_ENTRY_FLAG, s);
  651. }
  652.  
  653. /*
  654.     TRACEPB and ENTER_TRACE macros--Enter a new nesting level.
  655.     (Mark II Version).
  656. */
  657. int
  658. sl2pbtrace(sl_node **pp, char *s)
  659. {
  660.     if (*pp == NULL) {
  661.         *pp = sl_find("TRACEPB", s);
  662.     }
  663.     if (sl_visit(*pp, STAT_FLAG, ENTRY_FLAG, s)) {
  664.         sl_dots(sl_level-1);
  665.         es(s); es(": ");
  666.         return TRUE;
  667.     }
  668.     else {
  669.         return FALSE;
  670.     }
  671. }
  672.  
  673. /*
  674.     TRACEPN macro.
  675.     (Mark II Version.)
  676. */
  677. int
  678. sl2pntrace(sl_node **pp, char *s)
  679. {
  680.     if (*pp == NULL) {
  681.         *pp = sl_find("TRACEPN", s);
  682.     }
  683.     if (sl_visit(*pp, NO_STAT_FLAG, NO_ENTRY_FLAG, s)) {
  684.         sl_dots(sl_level-1);
  685.         es(s); es(": ");
  686.         return TRUE;
  687.     }
  688.     else {
  689.         return FALSE;
  690.     }
  691. }
  692.  
  693. /*
  694.     TRACEP macro--TRACE with printing of tracepoint's name.
  695.     (Mark II Version.)
  696. */
  697. int
  698. sl2ptrace(sl_node **pp, char *s)
  699. {
  700.     if (*pp == NULL) {
  701.         *pp = sl_find("TRACEP", s);
  702.     }
  703.     if (sl_visit(*pp, STAT_FLAG, NO_ENTRY_FLAG, s)) {
  704.         sl_dots(sl_level-1);
  705.         es(s); es(": ");
  706.         return TRUE;
  707.     }
  708.     else {
  709.         return FALSE;
  710.     }
  711. }
  712.  
  713. /*
  714.     STAT macro--Update one statistic.
  715.     (Mark II Version.)
  716. */
  717. void
  718. sl2stat(sl_node **pp, char * s)
  719. {
  720.     if (*pp == NULL) {
  721.         *pp = sl_find("STAT", s);
  722.     }
  723.     sl_visit(*pp, STAT_FLAG, NO_ENTRY_FLAG, s);
  724. }
  725.  
  726. /*
  727.     TICK macro--Update one statistic and print tracepoint's name.
  728.     (Mark II Version.)
  729. */
  730. void
  731. sl2tick(sl_node **pp, char * s)
  732. {
  733.     if (*pp == NULL) {
  734.         *pp = sl_find("TICK", s);
  735.     }
  736.     if (sl_visit(*pp, STAT_FLAG, NO_ENTRY_FLAG, s)) {
  737.         sl_dots(sl_level-1);
  738.         es(s); es(":"); enl();
  739.     }
  740. }
  741.  
  742. /*
  743.     TRACE macro--Return TRUE if tracing s.
  744.     (Mark II Version.)
  745. */
  746. int
  747. sl2trace(sl_node **pp, char *s)
  748. {
  749.     if (*pp == NULL) {
  750.         *pp = sl_find("TRACE", s);
  751.     }
  752.     return sl_visit(*pp, STAT_FLAG, NO_ENTRY_FLAG, s);
  753. }
  754.